#include "Test.h"
#include "KmerCounter.h"

Test::Test(void)
{
}


Test::~Test(void)
{
}

void Test::test1() // build debruijn graph
{
	char buffer[MAXREADLENGTH];
	KmerVertex::KmerLength = 31;
	OneFilePairedFastaReader reader("..\\data\\test_1.fa");
	KmerCounter counter(reader, 3);
	cout <<"Total number of trusted k-mers: " <<counter.numOfTrusted() <<endl;
	reader.reset();
	DeBruijnGraphBuilder builder(reader, counter);
	ReadSet& readset = builder.getReadSet();
	DeBruijnGraph& dbgraph = builder.getDeBruijnGraph();
	GCOUNT_T numRead = readset.numOfRead();
	GCOUNT_T numKmer = dbgraph.numOfVertex();
	cout << "#Read: " << readset.numOfRead() <<endl;
	cout << "#Kmer: " << dbgraph.numOfVertex() <<endl;
	cout <<"First read: " << readset.getRead(0).decompressRead(dbgraph, buffer) <<endl;
	cout <<"Last read:  " << readset.getRead(numRead - 1).decompressRead(dbgraph, buffer) << endl;
	const KmerVertex* firstKmer = dbgraph.getVertexByID(0);
	cout <<"First Kmer: " << firstKmer->DecompressKmer(buffer) << endl;
	cout <<"Last Kmer:   " << dbgraph.getVertexByID(numKmer - 1)->DecompressKmer(buffer) << endl;
	cout <<"First Kmer has " << firstKmer->numOfPredecessors() << " predecessors and "
		<< firstKmer->numOfSuccessors() <<" successors" << endl;
	if (firstKmer->numOfSuccessors() == 1) {
		cout <<"The only successor is " << dbgraph.getOnlySuccessor(firstKmer)->DecompressKmer(buffer)
			<<endl;
	}
	if (firstKmer->numOfPredecessors() == 1) {
		cout <<"The only predecessor is " << dbgraph.getOnlyPredecessor(firstKmer)->DecompressKmer(buffer)
			<<endl;
	}
}

void Test::test2() // build sequence graph (initial merge)
{
	char buffer[MAXREADLENGTH];
	KmerVertex::KmerLength = 31;
	OneFilePairedFastaReader reader("..\\data\\test_2.fa");
	KmerCounter counter(reader, 3);
	cout <<"Total number of trusted k-mers: " <<counter.numOfTrusted() <<endl;
	reader.reset();
	DeBruijnGraphBuilder builder(reader, counter);
	ReadSet& readset = builder.getReadSet();
	DeBruijnGraph& dbgraph = builder.getDeBruijnGraph();
	GCOUNT_T numRead = readset.numOfRead();
	GCOUNT_T numKmer = dbgraph.numOfVertex();
	SequenceGraph seqgraph(dbgraph, readset);
	cout << "#Vertex: " <<seqgraph.numOfVertex() <<endl;
	seqgraph.resetCursor();
	while (seqgraph.hasNext()) {
		cout << seqgraph.next()->decompressVertex(seqgraph, buffer) <<endl;
	}
}

void Test::test3() // remove tips
{
	char buffer[MAXREADLENGTH];
	KmerVertex::KmerLength = 31;
	OneFilePairedFastaReader reader("..\\data\\test_3.fa");
	KmerCounter counter(reader, 3);
	cout <<"Total number of trusted k-mers: " <<counter.numOfTrusted() <<endl;
	reader.reset();
	DeBruijnGraphBuilder builder(reader, counter);
	ReadSet& readset = builder.getReadSet();
	DeBruijnGraph& dbgraph = builder.getDeBruijnGraph();
	GCOUNT_T numRead = readset.numOfRead();
	GCOUNT_T numKmer = dbgraph.numOfVertex();
	SequenceGraph seqgraph(dbgraph, readset);
	cout << "#Vertex: " <<seqgraph.numOfVertex() <<endl;
	seqgraph.resetCursor();
	while (seqgraph.hasNext()) {
		cout << seqgraph.next()->decompressVertex(seqgraph, buffer) <<endl;
	}
	RemoveTips correction(&seqgraph, 62);
	correction.correctGraph();
	cout << "#Vertex: " <<seqgraph.numOfVertex() <<endl;
	seqgraph.resetCursor();
	while (seqgraph.hasNext()) {
		cout << seqgraph.next()->decompressVertex(seqgraph, buffer) << endl;
	}
}

void Test::test4() // remove bubbles
{
	char buffer[MAXREADLENGTH];
	KmerVertex::KmerLength = 31;
	OneFilePairedFastaReader reader("..\\data\\test_4.fa");
	KmerCounter counter(reader, 3);
	cout <<"Total number of trusted k-mers: " <<counter.numOfTrusted() <<endl;
	reader.reset();
	DeBruijnGraphBuilder builder(reader, counter);
	ReadSet& readset = builder.getReadSet();
	DeBruijnGraph& dbgraph = builder.getDeBruijnGraph();
	GCOUNT_T numRead = readset.numOfRead();
	GCOUNT_T numKmer = dbgraph.numOfVertex();
	SequenceGraph seqgraph(dbgraph, readset);
	cout << "#Vertex: " <<seqgraph.numOfVertex() <<endl;
	seqgraph.resetCursor();
	while (seqgraph.hasNext()) {
		cout << seqgraph.next()->decompressVertex(seqgraph, buffer) <<endl;
	}
	SimpleRemoveBubbles correction(&seqgraph,2*KmerVertex::KmerLength);
	correction.correctGraph();
	cout << "#Vertex: " <<seqgraph.numOfVertex() <<endl;
	seqgraph.resetCursor();
	while (seqgraph.hasNext()) {
		cout << seqgraph.next()->decompressVertex(seqgraph, buffer) << endl;
	}
}

void Test::test5() // low coverage
{
	//char buffer[MAXREADLENGTH*100];
	KmerVertex::KmerLength = 21;
	OneFilePairedFastaReader reader("..\\data\\test_reads.fa");
	KmerCounter counter(reader, 3);
	cout <<"Total number of trusted k-mers: " <<counter.numOfTrusted() <<endl;
	reader.reset();
	DeBruijnGraphBuilder builder(reader, counter);
	ReadSet& readset = builder.getReadSet();
	DeBruijnGraph& dbgraph = builder.getDeBruijnGraph();
	GCOUNT_T numRead = readset.numOfRead();
	GCOUNT_T numKmer = dbgraph.numOfVertex();
	SequenceGraph seqgraph(dbgraph, readset);
	cout << "#Vertex: " <<seqgraph.numOfVertex() <<endl;

	GraphErrorCorrector correction(&seqgraph, 42, 2, 5.0,100);
	correction.correctGraph();
	cout << "#Vertex: " <<seqgraph.numOfVertex() <<endl;
	int largeVertex = 0;
	seqgraph.resetCursor();
	while (seqgraph.hasNext()) {
		SequenceVertex* v = seqgraph.next();
		if (v->m_numOfKmer > 100) {
			++largeVertex;
			//cout << v->decompressVertex(seqgraph, buffer) << endl;
		}
	}
	cout <<"Large vertex: " << largeVertex << endl;
}

void Test::test6() // disambiguate with paired
{
	//char buffer[MAXREADLENGTH*100];
	char *buffer=new char[1024*1024];
	KmerVertex::KmerLength = 21;
	OneFilePairedFastaReader reader("..\\data\\test_read.fa");
	KmerCounter counter(reader, 3);
	cout <<"Total number of trusted k-mers: " <<counter.numOfTrusted() <<endl;
	reader.reset();
	DeBruijnGraphBuilder builder(reader, counter);
	ReadSet& readset = builder.getReadSet();
	DeBruijnGraph& dbgraph = builder.getDeBruijnGraph();
	GCOUNT_T numRead = readset.numOfRead();
	GCOUNT_T numKmer = dbgraph.numOfVertex();
	SequenceGraph seqgraph(dbgraph, readset);
	cout << "#Vertex: " <<seqgraph.numOfVertex() <<endl;

	GraphErrorCorrector correction(&seqgraph, 42, 2, 3.0,100);
	correction.correctGraph();
	cout << "#Vertex: " <<seqgraph.numOfVertex() <<endl;
	int largeVertex = 0;
	seqgraph.resetCursor();
	fstream fout("..\\output\\contig.txt",ios::out);
	while (seqgraph.hasNext()) {
		SequenceVertex* v = seqgraph.next();
		if (v->m_numOfKmer > 100) {
			++largeVertex;
			fout<<"contig:"<<largeVertex<<endl;
			fout << v->decompressVertex(seqgraph, buffer) << endl;
		}
	}
	fout.close();
	cout <<"Large vertex: " << largeVertex << endl;
	VelvetLibrary library(100, 10);
	Disambiguation disambiguation(&seqgraph, &library, &readset);
	disambiguation.findPaths();
	disambiguation.outputContigs();
	delete []buffer;
}

void Test::heapTest()
{
	class HeapNode: public AbstractHeapNode {
	public:
		double key;
		HeapNode(double k): key(k) {}
		static int cmp_func(void* node1, void* node2)
		{
			assert(node1 != NULL && node2 != NULL);
			HeapNode* ele1 = (HeapNode*) node1;
			HeapNode* ele2 = (HeapNode*) node2;
			if (ele1 == ele2 || ele1->key == ele2->key) {
				return 0;
			} else if (ele1->key > ele2->key) {
				return 1;
			} else {
				return -1;
			}
		}
	};
	FibHeap heap(HeapNode::cmp_func);
	srand((unsigned int)time(NULL));
	double keys[10] = {0.0, 12.34, 78.33, 233.9, -10, 100000, 32979.8, -877.9, 5000, -0.1};
	HeapNode* toDecrease1 = new HeapNode(888999);
	HeapNode* toDecrease2 = new HeapNode(3333);

	for (int i = 0; i < 10; ++i) {
		heap.insert(new HeapNode(keys[i]));
	}
	heap.insert(toDecrease1);
	heap.insert(toDecrease2);

	HeapNode* decreased1 = new HeapNode(*toDecrease1);
	decreased1->key = 888.999;
	HeapNode* decreased2 = new HeapNode(*toDecrease2);
	decreased2->key = 3.333;
	heap.decreaseKey(toDecrease1, decreased1);
	heap.decreaseKey(toDecrease2, decreased2);

	while (!heap.isEmpty()) {
		HeapNode* min = (HeapNode*)heap.extractMin();
		cout << min->key << endl;
		delete min;
	}
}

//void Test::test_simpleVertex()
//{
//	KmerVertex::KmerLength=5;
//	SimpleKmerVertex kV;
//	char s1[6];
//	while(1)
//	{
//		cin>>s1;
//		kV.Kmer=KmerVertex::CompressKmer(s1);
//		//SimpleKmerVertex *ktv=kV.reverseComplement();
//		CompressedKmer ktv=kV.reverseComplementKmer();
//		char s[100];
//		//KmerVertex::DecompressKmer(kV.Kmer,s);
//		//cout<<s<<endl;
//
//		KmerVertex::DecompressKmer(ktv,s);
//		cout<<s<<endl;
//	}
//}
//
//void Test::test_simpleHashTable()
//{
//	SimpleKmerHashTable ht;
//	CompressedKmer k=1;
//	SimpleKmerVertex sv;
//	sv.Kmer=k;
//	ht.Puts(&sv.Kmer,&sv);
//	printf("%ld\n",ht.Gets(&sv.Kmer)->Kmer);
//	CompressedKmer t = 200000000000LL;
//	if(ht.Gets(&t)==NULL)
//		cout<<"NULL"<<endl;
//}

void Test::test_memory()
{
	GINT64 i,bound;
	bound=1;
	for(i=0;i<27;++i)
		bound<<=1;
	for(i=0;i<bound;++i)
		new CompressedKmer;
}

void Test::test_openKmerNumTxt()
{
	GINT64 m_KmerNum;
	fstream fp("kmerNum.txt",ios::in);
	if(!fp)
	{
		cout<<"can not open kmerNum.txt which includes the total kmer Number"<<endl;
		exit(0);
	}
	int kmerLength=-1;
	if(!(fp>>kmerLength))
	{
		cout<<"can not input the kmerLength from kmerNum.txt"<<endl;
		exit(0);
	}
	if(kmerLength!=21)
	{
		cout<<"kmerLength"<<kmerLength<<" does not match"<<endl;
		exit(0);
	}
	if(!(fp>>m_KmerNum))
	{
		cout<<"can not input the kmer number from kmerNum.txt"<<endl;
		exit(0);
	}
	cout<<"kmerLength: "<<kmerLength<<endl;
	cout<<"kmerNum: "<<m_KmerNum<<endl;
	cout<<"success"<<endl;
}

void Test::test_temp()
{
	int bound=742538;
	int i;
	for(i=0;i<bound;++i)
		new KmerVertex(1,1,1,1);
	cout<<742538*sizeof(KmerVertex)/(double)1024/1024<<endl;
}
